package pl.us.ij.plugins.segmentation.commands.cvt;

import ij.process.FloatProcessor;
import ij.process.ImageProcessor;
import pl.us.ij.plugins.segmentation.Trace;
import pl.us.ij.plugins.segmentation.commands.MatrixHelper;
import pl.us.ij.plugins.segmentation.infrastructure.Command;
import pl.us.ij.plugins.segmentation.infrastructure.exceptions.BreakCommandException;

/**
 * Created by IntelliJ IDEA.
 * User: Przemek
 * Date: 2010-01-07
 * Time: 02:26:46
 * To change this template use File | Settings | File Templates.
 */
public class CvtShowEdgesCommand extends Command {
    @Override
    protected void processImage(FloatProcessor fp) throws BreakCommandException {
        int width = fp.getWidth();
        int height = fp.getHeight();

        ImageProcessor ip = fp;

        float[] copyPixels = (float[]) ip.getPixelsCopy();
        float[] pixels = (float[]) ip.getPixels();

        float[][] mask = MatrixHelper.floatMatrix(3, 0, 1, 0, 1, -4, 1, 0, 1, 0);

        mask(mask, width, height, pixels, true);


        for (int y = 0; y < height; y++) {
            int shiftD = y * width;

            for (int x = 0; x < width; x++) {
                if (pixels[shiftD + x] > 128) {
                    pixels[shiftD + x] = 255;
                } else {
                    pixels[shiftD + x] = copyPixels[shiftD + x];
                }
            }
        }

//        fp.setPixels(0, (FloatProcessor) ip);
    }

    private void mask(float[][] mask, int width, int height, float[] outPixels, boolean replacePixels) {
        float[][] h = MatrixHelper.floatZeros(3);
        float[] pixels = outPixels.clone();

        boolean logDone = false;

        for (int y = 1; y < height - 1; y++) {

            int shift0 = (y - 1) * width;
            int shift1 = y * width;
            int shift2 = (y + 1) * width;
            int shiftD = y * width;

            for (int x = 1; x < width - 1; x++) {
                h[0][0] = (pixels[shift0 + x - 1]);
                h[0][1] = (pixels[shift0 + x]);
                h[0][2] = (pixels[shift0 + (x + 1)]);

                h[1][0] = (pixels[shift1 + (x - 1)]);
                h[1][1] = (pixels[shift1 + x]);
                h[1][2] = (pixels[shift1 + (x + 1)]);

                h[2][0] = (pixels[shift2 + (x - 1)]);
                h[2][1] = (pixels[shift2 + x]);
                h[2][2] = (pixels[shift2 + (x + 1)]);

                h = MatrixHelper.floatMultiply(h, mask);

                float maskSum = MatrixHelper.floatSum(mask);

                if (maskSum == 0)
                    maskSum = 9;

                if (!logDone) {
                    Trace.log("Mask:");
                    Trace.log("" + h[0][0] + "," + h[0][1] + "," + h[0][2]);
                    Trace.log("" + h[1][0] + "," + h[1][1] + "," + h[1][2]);
                    Trace.log("" + h[2][0] + "," + h[2][1] + "," + h[2][2]);
                    Trace.log("Mask Sum:" + maskSum);
                }
                if (replacePixels) {
                    if (!logDone)
                        Trace.log("Prev:" + outPixels[shiftD + x]);

                    outPixels[shiftD + x] = Math.round(normalize(MatrixHelper.floatSum(h) / maskSum));
                    if (!logDone)
                        Trace.log(" Calc V:" + outPixels[shiftD + x]);

                    logDone = true;
                } else {
                    outPixels[shiftD + x] += (MatrixHelper.floatSum(h) / 9);
                }
            }
        }
    }

    public static float normalize(float v) {
        v %= 256;
        return v < 0
                ? 255 + v
                : v;
    }
}
